package framework.sepal4java.webserver;

import com.alibaba.fastjson.JSONObject;
import com.sun.net.httpserver.Headers;
import com.sun.net.httpserver.HttpContext;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpServer;
import framework.sepal4java.common.struct.SensorData;
import framework.sepal4java.common.util.Util;
import framework.sepal4java.lib4app.AbstractApp;
import framework.sepal4java.lib4app.AppRemoteConnector;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.log4j.PropertyConfigurator;

import java.io.*;
import java.net.InetSocketAddress;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;


public class WebServer {
    static {
        File file = new File("output/log/webserver/");
        File oldFile = new File("output_old/log/webserver/");
        Util.copyDirectory(file, oldFile);
        Util.deleteDir(file);
        file.mkdirs();
        PropertyConfigurator.configure("Resources/config/log/log4jWebServer.properties");
    }
    static final Log logger = LogFactory.getLog(HTTPServer.class);
    static AppRemoteConnector connector;

    public static void main(String[] args) {
        try {
            connector = AppRemoteConnector.getInstance();
            connector.connectPlatform("127.0.0.1", 9090);
            if (connector.registerApp(new HttpApp())) {
                int port = 9092;
                HttpServer server = HttpServer.create(new InetSocketAddress(port), 0);
                HttpContext context = server.createContext("/");
                context.setHandler(WebServer::handleRequest);
                server.start();
                logger.info("[HttpServer]: HTTP Server started on port " + port);
            }
        } catch (IOException e) {
            System.out.println("Server failed to start: " + e.getMessage());
        }
    }

    private static void handleRequest(HttpExchange exchange) {
        // 设置 CORS 规则
        Headers headers = exchange.getResponseHeaders();
        headers.set("Access-Control-Allow-Origin", "*"); // 允许来自 http://localhost:3000 的请求
        headers.set("Access-Control-Allow-Methods", "GET, POST");
        headers.set("Access-Control-Allow-Headers", "Content-Type");

        logger.info("[Browser -> WebServer]: " + exchange.getRemoteAddress() + exchange.getRequestURI() + " " + exchange.getRequestMethod() + " " + exchange.getRequestHeaders() + " " + exchange.getRequestBody());
        if (!exchange.getRequestURI().getPath().equals("/data")) {
            return;
        }

        String requestMethod = exchange.getRequestMethod();
        try {
            if (requestMethod.equalsIgnoreCase("GET")) {
                handleGetRequest(exchange);
            } else if (requestMethod.equalsIgnoreCase("POST")) {
                handlePostRequest(exchange);
            }
        } catch (IOException e) {
            sendErrorResponse(exchange, "Server error: " + e.getMessage());
        }
    }

    private static void handleGetRequest(HttpExchange exchange) throws IOException {
        URI requestURI = exchange.getRequestURI();
        String query = requestURI.getQuery();
        Map<String, String> queryParams = parseQueryParams(query);
        JSONObject jo = new JSONObject();
        jo.putAll(queryParams);

        // ... use queryParams ...

        //String response = "GET request received. " + "Path: " + requestURI.getPath() + ". Params: " + queryParams;
        String response = connector.raw(jo.toJSONString());
//        response = response.replace("//huanhang", "\n");
        response = response.replace("//shuangyinhao", "\\\"");
        logger.info("[WebServer -> Browser]: " + response);

        exchange.getResponseHeaders().set("Connection", "Keep-Alive");
        exchange.sendResponseHeaders(200, response.getBytes().length);
        OutputStream os = exchange.getResponseBody();
        os.write(response.getBytes());
        os.close();
    }

    private static void handlePostRequest(HttpExchange exchange) throws IOException {
        InputStreamReader isr = new InputStreamReader(exchange.getRequestBody(), StandardCharsets.UTF_8);
        BufferedReader br = new BufferedReader(isr);
        String requestBody = br.lines().collect(Collectors.joining(System.lineSeparator()));
        Map<String, String> postParams = parseQueryParams(requestBody);
        JSONObject jo = new JSONObject();
        jo.putAll(postParams);

        // ... use postParams ...

        String response = connector.raw(jo.toJSONString());
//        response = response.replace("//huanhang", "\n");
        response = response.replace("//shuangyinhao", "\\\"");
        logger.info("[WebServer -> Browser]: " + response);

        exchange.getResponseHeaders().set("Connection", "Keep-Alive");
        exchange.sendResponseHeaders(200, response.getBytes().length);
        OutputStream os = exchange.getResponseBody();
        os.write(response.getBytes());
        os.close();
    }

    private static Map<String, String> parseQueryParams(String query) {
        Map<String, String> queryParams = new HashMap<>();
        if (query != null) {
            String[] params = query.split("&");
            for (String param : params) {
                String[] nameValuePair = param.split("=");
                if (nameValuePair.length > 1) {
                    queryParams.put(nameValuePair[0], nameValuePair[1]);
                }
            }
        }
        if (!queryParams.containsKey("app_name")) {
            queryParams.put("app_name", "WebServer");
        }
        return queryParams;
    }

    private static void sendErrorResponse(HttpExchange exchange, String errorMessage) {
        try {
            byte[] response = errorMessage.getBytes();
            exchange.sendResponseHeaders(500, response.length);
            OutputStream os = exchange.getResponseBody();
            os.write(response);
            os.close();
        } catch (IOException e) {
            System.out.println("Failed to send error response: " + e.getMessage());
        }
    }

    static class HttpApp extends AbstractApp {

        @Override
        public void getMsg(String sensorName, SensorData value) {

        }

        @Override
        public void configApp() {
            this.appName = "WebServer";
            this.appDescription = "WebServer";
        }
    }
}
